#include "mw.h"
#include "ui_mw.h"
#include <qmessagebox.h>
#include "serialthread.h"
#include <QDebug>
#include <QFileDialog>
#include <QDateTime>
#include "convertool.h"
#define 串口配置文件 "配置文件/串口配置和解析方式/Config.ini"//相对路径，就在debug的首层文件夹


#define 查询命令 "配置文件/0201到0381实时数据.ini"//实时数据
//#define 查询命令 "配置文件/0382到0383最大最小值记录.ini"//电流电压剩余电流最大最小，发生时刻，最多命令的文件
//#define 查询命令 "配置文件/0388到0390报警记录.ini"//剩余电流超限，自检，跳闸，报警，512条数据大小记录
//#define 查询命令 "配置文件/0400到0601产品信息.ini"//产品信息
//#include <QVBoxLayout>
//#include <QHBoxLayout>
//#include <QGridLayout>
//#include <QPushButton>
//#include <QCheckBox>
//#include <QFormLayout>
//#include <QLineEdit>
//#include <QScrollBar>
//#include<QTimer>
#include <synchapi.h>

MW::MW(QWidget *parent): QMainWindow(parent) , ui(new Ui::MW)
{
    ui->setupUi(this);
   // setWindowIcon(QIcon("MandunDLT645.ico"));

    串口打开状态=0;
    checkDataForm已创建=false;

    //查找可用的串口
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort FindSerial;
        FindSerial.setPort(info);
        if(FindSerial.open(QIODevice::ReadWrite))
        {
            ui->PortBox->addItem(FindSerial.portName());
            FindSerial.close();
        }
    }

    thread = new QThread;//Qt中的线程类，这里用作子线程
    SerThr = new SerialThread;
    SerThr->moveToThread(thread);
    thread->start();

    connect(this,&MW::sendDataSignal,SerThr,&SerialThread::sendData);//mw主界面发送数据

    connect(this,&MW::sendConj,SerThr,&SerialThread::getConj);//串口配置

    connect(SerThr,&SerialThread::openedCom,this,&MW::comOpened);
    connect(SerThr,&SerialThread::openedCom,cdf,&CheckDataForm::comState);//使子窗口读取知悉串口状态
    connect(SerThr,&SerialThread::sendReceiveData,this,&MW::receiveData);//串口接收到数据，发送mw窗口中。
    connect(this,&MW::sendMWdata,cdf,&CheckDataForm::receiveMWsend);//MW界面发送的数送到checkdataform中显示

    //要注册QList<int>，才能跨线程发送List类型
    qRegisterMetaType<QList<int>>("QList<int>");
    comConj<<0<<0<<0<<0<<0;




    //从串口配置文件，更新控件的值
    QStringList 串口配置=Read_CONFIG_INI(串口配置文件,"baseConfigure", "comConj");

    if(串口配置[0]=="错误！没有对应的键")//找不到配置文件则新建一个
    {
        qDebug()<<"串口配置.isEmpty()"<<串口配置.isEmpty();
        QStringList 默认配置;
        默认配置<<"3"<<"2"<<"0"<<"3"<<"0";
        Write_CONFIG_INI(串口配置文件, "baseConfigure", "comConj",默认配置);
        串口配置=Read_CONFIG_INI(串口配置文件,"baseConfigure", "comConj");
    }

    ui->BaudBox->setCurrentIndex(串口配置[0].toInt());
    ui->ParityBox->setCurrentIndex(串口配置[1].toInt());
    ui->StopBox->setCurrentIndex(串口配置[2].toInt());
    ui->BitBox->setCurrentIndex(串口配置[3].toInt());
    ui->flowControlBox->setCurrentIndex(串口配置[4].toInt());

//表格文件设置
     ui->tableWidget->setColumnCount(4);
     ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"自动读?"<<"编码"<<"含义"<<"返回解析");
     ui->tableWidget->setRowCount(500);

     ui->tableWidget->setColumnWidth(0,50);
     ui->tableWidget->setColumnWidth(1,100);
     ui->tableWidget->setColumnWidth(2,200);
     ui->tableWidget->setColumnWidth(3,750);

     QSettings settings(查询命令, QSettings::IniFormat);
     settings.setIniCodec("UTF-8"); // 让 ini 支持中文
     keys = settings.allKeys();

     QStringList 命令;

     for(int i=0;i<keys.length();i++)
     {
        命令=Read_CONFIG_INI(查询命令,"", keys[i]);
        ui->tableWidget->setItem(i,0,new QTableWidgetItem(命令[0]));
        ui->tableWidget->setItem(i,1,new QTableWidgetItem(keys[i]));
        ui->tableWidget->setItem(i,2,new QTableWidgetItem(命令[1]));
        //qDebug()<<"keys.length()"<<命令;
     }

    第几个键=0;
    未收到需等待=0;
    是否写入到table=0;
    time1 = new QTimer(this);
    time2 = new QTimer(this);
    connect(time1,&QTimer::timeout,this,[=](){MW::sendDataSlot();});
    connect(time2,&QTimer::timeout,this,[=](){MW::SENDgetELdata();});
    ui->pButt_start->setEnabled(false);//串口未开，不允许读取
    ui->pButt_getELdata->setEnabled(false);//串口未开，不允许读取
    ui->pButt_updateTime->setEnabled(false);//串口未开，不允许读取
    ui->pButt_changeELadd->setEnabled(false);//串口未开，不允许读取
    ui->pButt_clear->setEnabled(false);//串口未开，不允许读取
    ui->pushButton_2->setEnabled(false);//停止按键，不能按

    ELadd=ui->lineE_ELadd->text();//从界面得到塑壳的地址
    ui->label_clear->clear();//清除框的数据
    ui->lineE_INIfile->setText("0201到0381实时数据.ini");

}




MW::~MW()
{
    delete ui;
}


//刷新串口列表
void MW::on_pushButton_clicked()
{
    ui->PortBox->clear();
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort FindSerial;
        FindSerial.setPort(info);
        if(FindSerial.open(QIODevice::ReadWrite))
        {
            ui->PortBox->addItem(FindSerial.portName());
            FindSerial.close();
        }
    }
}


//打开或关闭串口
void MW::on_openSerial_clicked()
{
    comNo=ui->PortBox->currentText();//设置串口号
    comConj[0]=ui->BaudBox->currentIndex();//设置波特率
    comConj[1]=ui->ParityBox->currentIndex();//设置校验位
    comConj[2]=ui->StopBox->currentIndex();//设置停止位
    comConj[3]=ui->BitBox->currentIndex();//设置数据位数
    comConj[4]=ui->flowControlBox->currentIndex();//设置流控制
    qDebug()<<"串口号"<<comNo<<"配置"<< comConj;

    QStringList 串口配置新;
    for(int i=0;i<5;i++)
    {
        串口配置新.append(QString::number(comConj[i]));
    }
    QStringList 串口配置旧=Read_CONFIG_INI(串口配置文件,"baseConfigure", "comConj");

    if(串口配置新!=串口配置旧){//防止多次更改文件，只有配置有更改，才写入到配置文件中
       Write_CONFIG_INI(串口配置文件,"baseConfigure", "comConj",串口配置新);
    }


    //发送串口配置
    emit sendConj(comNo,comConj);

}

//串口的打开和关闭对控件的使能和显示
void MW::comOpened(int 串口状态)
{
    qDebug()<<"主线程"<<QThread::currentThread();
    串口打开状态=串口状态;
    if(串口状态==1)//打开了串口
    {
        //关闭设置菜单使能
        ui->openSerial->setText(tr("关闭串口"));
        ui->pushButton->setEnabled(false);
        ui->PortBox->setEnabled(false);
        ui->BaudBox->setEnabled(false);
        ui->ParityBox->setEnabled(false);
        ui->BitBox->setEnabled(false);
        ui->StopBox->setEnabled(false);
        ui->flowControlBox->setEnabled(false);

        ui->pButt_start->setEnabled(true);
        ui->pButt_getELdata->setEnabled(true);
        ui->pButt_updateTime->setEnabled(true);
        ui->pButt_changeELadd->setEnabled(true);
        ui->pButt_clear->setEnabled(true);

        ui->lineE_ELadd_2->clear();
        ui->lineE_model->clear();
        ui->lineE_YMD->clear();
        ui->lineE_hms->clear();
        ui->label_clear->clear();

    }

    else if(串口状态==2)//关闭了串口
    {
        ui->openSerial->setText(tr("打开串口"));
        ui->pushButton->setEnabled(true);
        ui->PortBox->setEnabled(true);
        ui->BaudBox->setEnabled(true);
        ui->ParityBox->setEnabled(true);
        ui->BitBox->setEnabled(true);
        ui->StopBox->setEnabled(true);
        ui->flowControlBox->setEnabled(true);

        ui->pButt_start->setEnabled(false);//串口未开，不允许读取
        ui->pButt_getELdata->setEnabled(false);
        ui->pButt_updateTime->setEnabled(false);
        ui->pButt_changeELadd->setEnabled(false);
        ui->pButt_clear->setEnabled(false);
    }
    else if(串口状态==3)//串口不能正常打开
    QMessageBox::information(NULL, "提示", "串口无法打开");

}


//打开645调试界面调试
void MW::on_pButt_645test_clicked()
{
    //新建窗口和显示窗口
    if(!checkDataForm已创建)//如果还未创建
    {
     checkDataForm已创建=true;
    //CheckDataForm *cdf = new CheckDataForm;//必须使用new才正常。
    cdf->show();//显示645调试窗口必须使用->才正常，不能用点.

    connect(cdf,&CheckDataForm::sendData2,SerThr,&SerialThread::sendData);//CheckDataForm界面发送数据
    connect(SerThr,&SerialThread::sendReceiveData,cdf,&CheckDataForm::receiveData);//串口接收到数据，发送cdf窗口中。
    connect(this,&MW::comState,cdf,&CheckDataForm::comState);//使子窗口读取知悉串口状态
    }
    else{ cdf->hide();}//先隐藏，再显示，cdf窗口就到最前面了

    cdf->show();
    emit comState(串口打开状态);//使子窗口读取知悉串口状态
}


//由sendDataSlot槽接收将要发送的数据后，并发送出去
void MW::sendDataSlot()
{
    QString 长度Str;
    if(未收到需等待==40)//等于6次共3S，每500m一次，设40是因为有些指令返回慢
    {
        emit sendMWdata("未接收到数据","无数据减33H");
        ui->tableWidget->setItem(第几个键,3,new QTableWidgetItem("未接收到数据"));
        第几个键++;未收到需等待=0;

    }
    if(未收到需等待==0){
        QByteArray 待发送= 生成DL645帧(ELadd,"11",&长度Str,keys[第几个键],"","","","");
        QString 减33H后;

        验证接收帧(待发送,&ELadd,&减33H后);

        emit sendMWdata(QBtAy转HEX字符串(待发送,1),减33H后);
        emit sendDataSignal(待发送);
        未收到需等待=1;//先置1，后面接收的MW::receiveData函数再置为0
    }
    else {未收到需等待++;}
}
//林洋DDS71型电表，地址：000012038381

//开始按表格读取数据
void MW::on_pButt_start_clicked()
{
    ELadd=ui->lineE_ELadd->text();//从界面得到塑壳的地址
    time1->start(500);
    第几个键=0;
    未收到需等待=0;
    是否写入到table=1;

    ui->pButt_selectINIfile->setEnabled(false);
    ui->pushButton_2->setEnabled(true);//停止按键，可以按
    ui->pButt_start->setEnabled(false);//在开始读时，不允许按

    ui->pButt_getELdata->setEnabled(false);
    ui->pButt_updateTime->setEnabled(false);
    ui->pButt_changeELadd->setEnabled(false);
    ui->pButt_clear->setEnabled(false);

}




void MW::receiveData(QByteArray Sdata)
{
    QString 减33H后;//在这只是用来匹配函数，没有作用
    QString 帧的解析=验证接收帧(Sdata,&ELadd,&减33H后);
    qDebug()<<"主窗口能否接收到数据?"<<帧的解析;
    if(是否写入到table==1)
    {
        //ui->textBr_commandMean->setText(接收的帧);
        ui->tableWidget->setItem(第几个键,3,new QTableWidgetItem(帧的解析));
        第几个键++;
        if(第几个键==keys.length()) {//读完数据后，停止定时和接收
            time1->stop();
            第几个键=0;

            ui->pButt_selectINIfile->setEnabled(true);
            是否写入到table=0;

            ui->pushButton_2->setEnabled(false);//停止按键，不能按
            ui->pButt_start->setEnabled(true);//读取完成才允许按
            ui->pButt_start->setEnabled(true);//
            ui->pButt_getELdata->setEnabled(true);

            ui->pButt_updateTime->setEnabled(true);
            ui->pButt_changeELadd->setEnabled(true);
            ui->pButt_clear->setEnabled(true);
        }
        未收到需等待=0;//设为0才允许后续再发送
        return;
    }

    if(是否写入到table==2)//获取数据
    {
        switch(第几个键)
        {
            case 0:ui->lineE_ELadd_2->setText(ELadd);ui->lineE_ELadd->setText(ELadd);break;
            case 1:ui->lineE_model->setText(帧的解析);break;
            case 2:ui->lineE_YMD->setText(帧的解析);break;
            case 3:ui->lineE_hms->setText(帧的解析);break;
        default:break;
        }
        第几个键++;

        if(第几个键==4) {//读完数据后，停止定时和接收
            time2->stop();
            第几个键=0;
            是否写入到table=0;

        }
        未收到需等待=0;
        return;
    }


    if(是否写入到table==3)//校准时间
    {
        switch(第几个键)
        {
            case 0:ui->lineE_ELadd_2->setText(ELadd);ui->lineE_ELadd->setText(ELadd);break;
            case 1:ui->lineE_model->setText(帧的解析);break;
            case 2:ui->lineE_YMD->setText(帧的解析);break;
            case 3:ui->lineE_hms->setText(帧的解析);break;
        default:break;
        }
        第几个键++;
        qDebug()<<"第几个键"<<第几个键;
        if(第几个键==7)第几个键=0;//第一次发的是校准时间的，所以不应显示到界面中

        if(第几个键==4) {//读完数据后，停止定时和接收
            time2->stop();
            第几个键=0;
            是否写入到table=0;
        }
        未收到需等待=0;
        return;
    }
    if(是否写入到table==4)//清除记录
    {
        ui->label_clear->setText(帧的解析);
        是否写入到table=0;
    }
}



void MW::on_pButt_getELdata_clicked()
{
    time2->start(500);
    第几个键=0;
    未收到需等待=0;
    是否写入到table=2;//不写到table中

}

//由SENDgetELdata()槽接收将要发送的数据后，并发送出去
void MW::SENDgetELdata()
{
    QString 长度Str;
    if(未收到需等待==40)//等于6次共3S，每500m一次，设40是因为有些指令返回慢
    {
        time2->stop();
        第几个键=0;
        未收到需等待=0;
        QMessageBox::information(NULL, "提示", "无法得到塑壳数据");;
    }
    if(未收到需等待==0){


       QByteArray 待发送;
       switch(第几个键)
       {
       case 0:待发送=生成DL645帧("AA AA AA AA AA AA","13",&长度Str,"","","","","");break;//地址
       case 1:待发送=生成DL645帧(ELadd,"11",&长度Str,"0400040B","","","","");break;//型号
       case 2:待发送=生成DL645帧(ELadd,"11",&长度Str,"04000101","","","","");break;//日期
       case 3:待发送=生成DL645帧(ELadd,"11",&长度Str,"04000102","","","","");break;//时分秒
       default:待发送=生成DL645帧("AA AA AA AA AA AA","13",&长度Str,"","","","","");break;
       }

       // QByteArray 待发送= 生成DL645帧(ELadd,"11",&长度Str,keys[第几个键],"","","","");


        emit sendDataSignal(待发送);
        未收到需等待=1;//先置1，后面接收的MW::receiveData函数再置为0
    }
    else {未收到需等待++;}
}

void MW::on_pButt_updateTime_clicked()
{
    QDateTime dateTime = QDateTime ::currentDateTime();
    QString 时间= dateTime.toString("yyMMddhhmmss");


    QByteArray 待发送;

    待发送=生成DL645帧("AA AA AA AA AA AA","8",&时间,时间,"","","","");//&时间是没用的，只是表示指针而已
    //不知为什么输入08，生成的帧没有时间。
    第几个键=6;
    未收到需等待=0;
    是否写入到table=3;//不写到table中

    emit sendDataSignal(待发送);

    time2->start(500);


}




void MW::on_pButt_changeELadd_clicked()
{
    QByteArray 待发送;
    QString 长度str,新地址;
    新地址=ui->lineE_updateELadd->text();//从界面得到塑壳的新地址

    待发送=生成DL645帧("AA AA AA AA AA AA","15",&长度str,"","","",新地址,"");//&长度str是没用的，只是表示指针而已
    //不知为什么输入08，生成的帧没有时间。
    第几个键=6;
    未收到需等待=0;
    是否写入到table=3;//不写到table中

    emit sendDataSignal(待发送);


    time2->start(500);
}


void MW::on_pButt_clear_clicked()
{
    QString 长度str;

    QByteArray 待发送;
    待发送=生成DL645帧("AA AA AA AA AA AA","1B",&长度str,"","00000000","01020304","FFFFFFFF","");//&长度str是没用的，只是表示指针而已
    是否写入到table=4;//不写到table中
    emit sendDataSignal(待发送);
}


void MW::on_pButt_selectINIfile_clicked()
{
   // QString filePath = QFileDialog::getExistingDirectory(this, "请选择文件保存路径…", "./");
    QString 查询命令2 = QFileDialog::getOpenFileName(this,tr("ini文件选取"),"./配置文件",tr("*.ini"));


    if(!查询命令2.isEmpty())
    {
        ui->tableWidget->clearContents();//清空所有内容，除了表头

        ui->lineE_INIfile->setText(查询命令2);
        QSettings settings(查询命令2, QSettings::IniFormat);
        settings.setIniCodec("UTF-8"); // 让 ini 支持中文
        keys = settings.allKeys();
        QStringList 命令;

        //qDebug()<<"keys.length()"<<keys;
        for(int i=0;i<keys.length();i++)
        {
            命令=Read_CONFIG_INI(查询命令2,"", keys[i]);

            ui->tableWidget->setItem(i,0,new QTableWidgetItem(命令[0]));
            ui->tableWidget->setItem(i,1,new QTableWidgetItem(keys[i]));
            ui->tableWidget->setItem(i,2,new QTableWidgetItem(命令[1]));

        }
        qDebug()<<"keys.length()"<<命令;

    }

}


void MW::on_pushButton_2_clicked()
{
    qDebug()<<"停止键按下";
    time1->stop();
    第几个键=0;
    是否写入到table=0;
    ui->pButt_selectINIfile->setEnabled(true);
    ui->pushButton_2->setEnabled(false);//停止按键，不能按
    ui->pButt_start->setEnabled(true);//
    ui->pButt_getELdata->setEnabled(true);

    ui->pButt_updateTime->setEnabled(true);
    ui->pButt_changeELadd->setEnabled(true);
    ui->pButt_clear->setEnabled(true);


}

